<?php

// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2010 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// $Id: Think.class.php 647 2012-01-17 09:05:10Z luofei614@126.com $

/**
  +------------------------------------------------------------------------------
 * ThinkPHP Portal类
  +------------------------------------------------------------------------------
 * @category   Think
 * @package  Think
 * @subpackage  Core
 * @author    liu21st <liu21st@gmail.com>
 * @version   $Id: Think.class.php 647 2012-01-17 09:05:10Z luofei614@126.com $
  +------------------------------------------------------------------------------
 */
class Think {

    private static $_instance = array();

    /**
      +----------------------------------------------------------
     * 应用程序初始化
      +----------------------------------------------------------
     * @access public
      +----------------------------------------------------------
     * @return void
      +----------------------------------------------------------
     */
    static public function Start() {
        // 设定错误和异常处理
        set_error_handler(array('Think', 'appError'));
        set_exception_handler(array('Think', 'appException'));
        // 注册AUTOLOAD方法
        spl_autoload_register(array('Think', 'autoload'));
        //[RUNTIME]
        Think::buildApp();         // 预编译项目
        //[/RUNTIME]
        // 运行应用
        App::run();
        return;
    }

    //[RUNTIME]
    /**
      +----------------------------------------------------------
     * 读取配置信息 编译项目
      +----------------------------------------------------------
     * @access private
      +----------------------------------------------------------
     * @return string
      +----------------------------------------------------------
     */
    static private function buildApp() {
        // 加载底层惯例配置文件
        C(include THINK_PATH . 'Conf/convention.php');

        // 读取运行模式
        if (defined('MODE_NAME')) { // 模式的设置并入核心模式
            $mode = include MODE_PATH . strtolower(MODE_NAME) . '.php';
        } else {
            $mode = array();
        }

        // 加载模式配置文件
        if (isset($mode['config'])) {
            C(is_array($mode['config']) ? $mode['config'] : include $mode['config'] );
        }

        // 加载项目配置文件
        if (is_file(CONFIG_PATH . 'config.php'))
            C(include CONFIG_PATH . 'config.php');
        //[sae]惯例配置
        C(include THINK_PATH . 'Sae/convention_sae.php');
        //[sae]专有配置
        if (is_file(CONFIG_PATH . 'config_sae.php'))
            C(include CONFIG_PATH . 'config_sae.php');
        // 加载框架底层语言包
        L(include THINK_PATH . 'Lang/' . strtolower(C('DEFAULT_LANG')) . '.php');

        // 加载模式系统行为定义
        if (C('APP_TAGS_ON')) {
            if (isset($mode['extends'])) {
                C('extends', is_array($mode['extends']) ? $mode['extends'] : include $mode['extends']);
            } else { //[sae] 默认加载系统行为扩展定义
                C('extends', include THINK_PATH . 'Sae/tags.php');
            }
        }

        // 加载应用行为定义
        if (isset($mode['tags'])) {
            C('tags', is_array($mode['tags']) ? $mode['tags'] : include $mode['tags']);
        } elseif (is_file(CONFIG_PATH . 'tags.php')) {
            // 默认加载项目配置目录的tags文件定义
            C('tags', include CONFIG_PATH . 'tags.php');
        }

        $compile = '';
        // 读取核心编译文件列表
        if (isset($mode['core'])) {
            $list = $mode['core'];
        } else {
            $list = array(
                THINK_PATH . 'Sae/functions.php', //[sae] 标准模式函数库
                THINK_PATH.'Sae/sae_functions.php',//[sae]新增sae专用函数
                THINK_PATH . 'Sae/Log.class.php', // 日志处理类
                CORE_PATH . 'Core/Dispatcher.class.php', // URL调度类
                CORE_PATH . 'Core/App.class.php', // 应用程序类
                CORE_PATH . 'Core/Action.class.php', // 控制器类
                CORE_PATH . 'Core/View.class.php', // 视图类
            );
        }
        foreach ($list as $file) {
            if (is_file($file)) {
                require_cache($file);
                if (!APP_DEBUG)
                    $compile .= compile($file);
            }
        }

        // 加载公共文件
        if (!isset($mode['common'])) { // 默认加载项目公共文件
            $mode['common'] = COMMON_PATH . 'common.php';
        }
        if (is_file($mode['common'])) {
            include $mode['common'];
            // 编译文件
            if (!APP_DEBUG)
                $compile .= compile($mode['common']);
        }

        // 加载应用别名定义
        if (isset($mode['alias'])) {
            $alias = is_array($mode['alias']) ? $mode['alias'] : include $mode['alias'];
        } elseif (is_file(CONFIG_PATH . 'alias.php')) {
            // 没有定义 则获取项目配置目录的alias别名定义文件
            $alias = include CONFIG_PATH . 'alias.php';
        }
        if (is_array($alias)) {
            alias_import($alias);
            if (!APP_DEBUG)
                $compile .= 'alias_import(' . var_export($alias, true) . ');';
        }

        if (APP_DEBUG) {
            // 调试模式加载系统默认的配置文件
            C(include THINK_PATH . 'Conf/debug.php');
            // 读取调试模式的应用状态
            $status = C('APP_STATUS');
            // 加载对应的项目配置文件
            if (is_file(CONFIG_PATH . $status . '.php'))
            // 允许项目增加开发模式配置定义
                C(include CONFIG_PATH . $status . '.php');
        }else {
            // 部署模式下面生成编译文件
            build_runtime_cache($compile);
        }
        return;
    }

    //[/RUNTIME]

    /**
      +----------------------------------------------------------
     * 系统自动加载ThinkPHP类库
     * 并且支持配置自动加载路径
      +----------------------------------------------------------
     * @param string $class 对象类名
      +----------------------------------------------------------
     * @return void
      +----------------------------------------------------------
     */
    public static function autoload($class) {
        // 检查是否存在别名定义
        if (alias_import($class))
            return;

        if (substr($class, -8) == "Behavior") { // 加载行为
            if (require_cache(CORE_PATH . 'Behavior/' . $class . '.class.php')
                    || require_cache(EXTEND_PATH . 'Behavior/' . $class . '.class.php')
                    || require_cache(LIB_PATH . 'Behavior/' . $class . '.class.php')
                    || (defined('MODE_NAME') && require_cache(MODE_PATH . ucwords(MODE_NAME) . '/Behavior/' . $class . '.class.php'))) {
                return;
            }
        } elseif (substr($class, -5) == "Model") { // 加载模型
            if (require_cache(LIB_PATH . 'Model/' . $class . '.class.php')
                    || require_cache(EXTEND_PATH . 'Model/' . $class . '.class.php')) {
                return;
            }
        } elseif (substr($class, -6) == "Action") { // 加载控制器
            if ((defined('GROUP_NAME') && require_cache(LIB_PATH . 'Action/' . GROUP_NAME . '/' . $class . '.class.php'))
                    || require_cache(LIB_PATH . 'Action/' . $class . '.class.php')
                    || require_cache(EXTEND_PATH . 'Action/' . $class . '.class.php')) {
                return;
            }
        }

        // 根据自动加载路径设置进行尝试搜索
        $paths = explode(',', C('APP_AUTOLOAD_PATH'));
        foreach ($paths as $path) {
            if (import($path . '.' . $class))
            // 如果加载类成功则返回
                return;
        }
    }

    /**
      +----------------------------------------------------------
     * 取得对象实例 支持调用类的静态方法
      +----------------------------------------------------------
     * @param string $class 对象类名
     * @param string $method 类的静态方法名
      +----------------------------------------------------------
     * @return object
      +----------------------------------------------------------
     */
    static public function instance($class, $method='') {
        $identify = $class . $method;
        if (!isset(self::$_instance[$identify])) {
            if (class_exists($class)) {
                $o = new $class();
                if (!empty($method) && method_exists($o, $method))
                    self::$_instance[$identify] = call_user_func_array(array(&$o, $method));
                else
                    self::$_instance[$identify] = $o;
            }
            else
                halt(L('_CLASS_NOT_EXIST_') . ':' . $class);
        }
        return self::$_instance[$identify];
    }

    /**
      +----------------------------------------------------------
     * 自定义异常处理
      +----------------------------------------------------------
     * @access public
      +----------------------------------------------------------
     * @param mixed $e 异常对象
      +----------------------------------------------------------
     */
    static public function appException($e) {
        halt($e->__toString());
    }

    /**
      +----------------------------------------------------------
     * 自定义错误处理
      +----------------------------------------------------------
     * @access public
      +----------------------------------------------------------
     * @param int $errno 错误类型
     * @param string $errstr 错误信息
     * @param string $errfile 错误文件
     * @param int $errline 错误行数
      +----------------------------------------------------------
     * @return void
      +----------------------------------------------------------
     */
    static public function appError($errno, $errstr, $errfile, $errline) {
        switch ($errno) {
            case E_ERROR:
            case E_USER_ERROR:
                $errorStr = "[$errno] $errstr " . basename($errfile) . " 第 $errline 行.";
                if (C('LOG_RECORD'))
                    Log::write($errorStr, Log::ERR);
                halt($errorStr);
                break;
            case E_STRICT:
            case E_USER_WARNING:
            case E_USER_NOTICE:
            default:
                $errorStr = "[$errno] $errstr " . basename($errfile) . " 第 $errline 行.";
                Log::record($errorStr, Log::NOTICE);
                break;
        }
    }

    /**
      +----------------------------------------------------------
     * 自动变量设置
      +----------------------------------------------------------
     * @access public
      +----------------------------------------------------------
     * @param $name 属性名称
     * @param $value  属性值
      +----------------------------------------------------------
     */
    public function __set($name, $value) {
        if (property_exists($this, $name))
            $this->$name = $value;
    }

    /**
      +----------------------------------------------------------
     * 自动变量获取
      +----------------------------------------------------------
     * @access public
      +----------------------------------------------------------
     * @param $name 属性名称
      +----------------------------------------------------------
     * @return mixed
      +----------------------------------------------------------
     */
    public function __get($name) {
        return isset($this->$name) ? $this->$name : null;
    }

}